﻿using System;
using System.Collections.Generic;
using System.Text;
using System.IO;
using Slippor.Douban.Radio.Assist;

namespace RestoreHandlerPlugin
{
    public class MP3
    {
        public string filePath; // MP3文件路径
        public string fileFileName; // MP3文件名称
        public string fileComplete; // MP3文件完全路径
        public bool hasID3Tag; // MP3文件标签头
        public string id3Title; // MP3文件标题
        public string id3Artist; // MP3艺人
        public string id3Album; // MP3专辑
        public string id3Year; // MP3年份
        public string id3Comment; // MP3备注
        public byte id3TrackNumber; // MP3曲目
        public byte id3Genre; // MP3曲风

        // Required struct constructor
        public MP3(string path, string name)
        {
            this.filePath = path;
            this.fileFileName = name;
            this.fileComplete = path + "\\" + name;
            this.hasID3Tag = false;
            this.id3Title = null;
            this.id3Artist = null;
            this.id3Album = null;
            this.id3Year = null;
            this.id3Comment = null;
            this.id3TrackNumber = 0;
            this.id3Genre = 0;
        }

        public MP3(Song song)
        {
            this.hasID3Tag = true;
            this.id3Title = song.Title;
            if (song.Album != null)
            {
                this.id3Artist = song.Album.ArtistString;
                this.id3Album = song.Album.Name;
                this.id3Year = song.Album.PublishDate;
                this.id3Comment = song.Album.Mark.ToString();
            }
            this.id3TrackNumber = 0;
            this.id3Genre = 0;
        }
    }

    public class MP3Header
    {
        public MP3Header()
        {
            //
            // TODO: 在此处添加构造函数逻辑
            //
        }

        /// <summary>
        /// 获得所选MP3文件的TAG头信息
        /// </summary>
        /// <param name="Path">MP3文件的绝对路径</param>
        /// <param name="Header">接受MP3头信息的变量</param>
        /// <ref>赋值给Header变量</ref>
        public static void ReadHeader(string Path, ref MP3 Header)
        {
            FileStream oFileStream;
            int i;
            oFileStream = new FileStream(Path, FileMode.Open);
            byte[] bBuffer = new byte[128];
            oFileStream.Seek(-128, SeekOrigin.End);
            oFileStream.Read(bBuffer, 0, 128);
            oFileStream.Close();

            byte[] tag = new byte[3];
            byte[] title = new byte[30];
            byte[] artist = new byte[30];
            byte[] album = new byte[30];
            byte[] year = new byte[4];
            byte[] comment = new byte[28];
            byte[] track = new byte[1];
            byte[] genre = new byte[1];

            for (i = 0; i < 3; i++)
            {
                tag[i] = bBuffer[i];
            }
            for (i = 3; i < 33; i++)
            {
                title[i - 3] = bBuffer[i];
            }
            for (i = 33; i < 63; i++)
            {
                artist[i - 33] = bBuffer[i];
            }
            for (i = 63; i < 93; i++)
            {
                album[i - 63] = bBuffer[i];
            }
            for (i = 93; i < 97; i++)
            {
                year[i - 93] = bBuffer[i];
            }
            for (i = 97; i < 125; i++)
            {
                comment[i - 97] = bBuffer[i];
            }
            for (i = 125; i < 126; i++)
            {
                track[i - 125] = bBuffer[i];
            }
            for (i = 126; i < 127; i++)
            {
                genre[i - 126] = bBuffer[i];
            }

            Header.id3Title = byteToString(title);
            Header.id3Artist = byteToString(artist);
            Header.id3Album = byteToString(album);
            Header.id3Year = byteToString(year);
            Header.id3Comment = byteToString(comment);
            Header.id3TrackNumber = bBuffer[126];
            Header.id3Genre = bBuffer[127];
            Header.hasID3Tag = true;
        }

        /// <summary>
        /// 设置所选MP3文件的TAG头信息
        /// </summary>
        /// <param name="path">MP3文件的绝对路径</param>
        /// <param name="Header">设置MP3头信息的变量</param>
        /// <ref>将变量Header得值赋给MP3文件</ref>
        public static void WriteHeader(string path, MP3 header)
        {
            byte[] tagByteArray = new byte[128];

            if (header.id3Title != null && header.id3Title.Length > 30) header.id3Title = header.id3Title.Substring(0, 30);
            if (header.id3Artist != null && header.id3Artist.Length > 30) header.id3Artist = header.id3Artist.Substring(0, 30);
            if (header.id3Album != null && header.id3Album.Length > 30) header.id3Album = header.id3Album.Substring(0, 30);
            if (header.id3Year != null && header.id3Year.Length > 4) header.id3Year = header.id3Year.Substring(0, 4);
            if (header.id3Comment != null && header.id3Comment.Length > 28) header.id3Comment = header.id3Comment.Substring(0, 28);

            for (int i = 0; i < tagByteArray.Length; i++) tagByteArray[i] = 0;

            Encoding instEncoding = Encoding.GetEncoding("GB2312");

            byte[] workingByteArray = instEncoding.GetBytes("TAG");
            Array.Copy(workingByteArray, 0, tagByteArray, 0, workingByteArray.Length);

            CopyInfo(tagByteArray, header.id3Title, instEncoding, 3);
            CopyInfo(tagByteArray, header.id3Artist, instEncoding, 33);
            CopyInfo(tagByteArray, header.id3Album, instEncoding, 63);
            CopyInfo(tagByteArray, header.id3Year, instEncoding, 93);
            CopyInfo(tagByteArray, header.id3Comment, instEncoding, 97);

            tagByteArray[126] = header.id3TrackNumber;
            tagByteArray[127] = header.id3Genre;

            FileStream oFileStream = new FileStream(path, FileMode.Open);
            if (header.hasID3Tag)
                oFileStream.Seek(-128, SeekOrigin.End);
            else
                oFileStream.Seek(0, SeekOrigin.End);
            oFileStream.Write(tagByteArray, 0, 128);
            oFileStream.Close();
        }

        private static void CopyInfo(byte[] tagByteArray, string info, Encoding instEncoding, int index)
        {
            if (info != null)
            {
                byte[] workingByteArray = instEncoding.GetBytes(info);
                Array.Copy(workingByteArray, 0, tagByteArray, index, workingByteArray.Length);
            }
        }

        private static string byteToString(byte[] b)
        {
            Encoding enc = Encoding.GetEncoding("GB2312");
            string str = enc.GetString(b);
            str = str.Substring(0, str.IndexOf('\0') >= 0 ? str.IndexOf('\0') : str.Length);//去掉无用字符
            return str;
        }
    } 
}
